import { GpEcsWorld } from "../../GpEcsWorld";
import { Comp } from "../../CompDef";
import { Sglt } from "../../SgltDefine";
import { MathUtils, Rectangle, Vect3 } from "../../../../common/MathUtils";
import { makeDamage } from "./Utils";
import { CommonSystem } from "../CommonSystem";
import { DamageEventInfo } from "./BattleSystem";
import ecs, { EcsComponent, EcsEntity, EcsEntityGroup } from "ecs-ts";
export class BulletSystem extends ecs.EcsSystem<GpEcsWorld> {
    tempVec3 = new Vect3()
    tempRect: Rectangle = new Rectangle()
    tempQueryResult: EcsEntity[] = []
    uiInfo: Sglt.UiInfo
    rayGroup: EcsEntityGroup = null

    constructor(world: GpEcsWorld, defaltGroupComps: (new () => EcsComponent)[] = [Comp.Transform, Comp.Battle.Bullet]) {
        super(world, defaltGroupComps);
        this.rayGroup = this.world.getGroupByClz(Comp.Battle.Ray)
        this.uiInfo = this.world.getSingleton(Sglt.UiInfo)
    }

    onBulletHit(entity: EcsEntity, bullet: Comp.Battle.Bullet, target: EcsEntity, targetBattleInfo: Comp.Battle.BattleInfo) {
        const bulletOwner = this.world.getEntity(bullet.emmiterId)
        if (bulletOwner && target) {
            const bulletOwnerBattleInfo = bulletOwner.component(Comp.Battle.BattleInfo)
            makeDamage(new DamageEventInfo(this.world, bulletOwner, bulletOwnerBattleInfo, target, targetBattleInfo))
        }
        if (bullet.passThrough >= bullet.maxPassThrough) {
            this.world.removeEntity(entity.id)
        }


    }

    /**锁定型子弹移动逻辑 */
    checkLockBulletMove(entity: EcsEntity, bullet: Comp.Battle.Bullet, locker: Comp.Battle.TargetLocker) {
        const transform = entity.component(Comp.Transform)
        const target = this.world.getEntity(locker.targetEntityId)
        let targetBattleInfo
        if (target) {
            const targetTransform = target.component(Comp.Transform)
            targetBattleInfo = target.component(Comp.Battle.BattleInfo)
            Vect3.set(locker.targetPos, targetTransform.pos.x, targetTransform.pos.y + targetTransform.height / 2, targetTransform.pos.z)
        }

        const targetPos = locker.targetPos
        const dir = Vect3.subtract(this.tempVec3, targetPos, transform.pos)
        const dirMag = Vect3.mag(dir)
        const moveDistance = bullet.speed * (this.world.elapsedMsPerFrame / 1000)
        if (dirMag < moveDistance) {
            transform.pos.x = targetPos.x
            transform.pos.y = targetPos.y
            transform.pos.z = targetPos.z
            bullet.passThrough++
            this.onBulletHit(entity, bullet, target, targetBattleInfo)
        } else {
            Vect3.normalize(dir, dir)
            Vect3.scaleAndAdd(transform.pos, transform.pos, dir, moveDistance)
        }
    }



    /**子弹移动逻辑 */
    checkBulletMove(entity: EcsEntity, bullet: Comp.Battle.Bullet) {
        const quadTree = this.world.system(CommonSystem).quadTree
        this.tempQueryResult.length = 0

        const transform = entity.component(Comp.Transform)

        if (Math.abs(transform.pos.x) > 2000 || Math.abs(transform.pos.y) > 2000) {
            this.world.removeEntity(entity.id)
            return
        }

        if (bullet.passThrough < bullet.maxPassThrough) {
            MathUtils.getRectInDirection(transform.pos, { x: 0, y: 0, z: 0 }, 200, 200, this.tempRect)
            this.tempQueryResult = quadTree.query(this.tempRect, this.tempQueryResult)

            for (let index = 0; index < this.tempQueryResult.length; index++) {
                if (bullet.passThrough < bullet.maxPassThrough) {
                    const queryItemEntity = this.tempQueryResult[index];

                    const battleInfo = queryItemEntity.component(Comp.Battle.BattleInfo)
                    const targetTransform = queryItemEntity.component(Comp.Transform)
                    const distance = Vect3.distance(transform.pos, targetTransform.pos)
                    if (distance > (transform.radius + targetTransform.radius)) {
                        continue
                    }
                    if (!bullet.passTargetMap[queryItemEntity.id] && battleInfo && battleInfo.__ownerId != bullet.emmiterId) {
                        bullet.passTargetMap[queryItemEntity.id] = 1
                        bullet.passThrough++
                        this.onBulletHit(entity, bullet, queryItemEntity, battleInfo)
                    }

                } else {
                    break
                }
            }
        }

        if (bullet.passThrough < bullet.maxPassThrough) {
            const dir = Vect3.set(this.tempVec3, transform.orientation)
            const moveDistance = bullet.speed * (this.world.elapsedMsPerFrame / 1000)

            Vect3.normalize(dir, dir)
            Vect3.scaleAndAdd(transform.pos, transform.pos, dir, moveDistance)
        }

    }

    update(): void {
        this.defaultGroup.forEach((entity) => {
            const bullet = entity.component(Comp.Battle.Bullet)
            const locker = entity.component(Comp.Battle.TargetLocker)
            if (locker) {
                this.checkLockBulletMove(entity, bullet, locker)
            } else if (entity.component(Comp.Battle.FlyBullet)) {
                this.checkBulletMove(entity, bullet)
            }

        })

        /**每秒检测一次 */
        if (this.world.frameCount % this.world.frameRate == 0) {
            this.rayGroup.forEach((entity) => {
                const ray = entity.component(Comp.Battle.Ray)
                const bullet = entity.component(Comp.Battle.Bullet)
                const centerPos = Vect3.getPosBetweenTowPoint(this.tempVec3, ray.startPos, ray.targetPos)

                MathUtils.getRectInDirection(centerPos, { x: 0, y: 0, z: 0 }, Comp.Battle.Ray.getCornerWidth(ray) * 2, Comp.Battle.Ray.getCornerHeight(ray) * 2, this.tempRect)
                const quadTree = this.world.system(CommonSystem).quadTree
                this.tempQueryResult.length = 0
                this.tempQueryResult = quadTree.query(this.tempRect, this.tempQueryResult)

                for (let index = 0; index < this.tempQueryResult.length; index++) {
                    const queryItemEntity = this.tempQueryResult[index];

                    if (queryItemEntity.id != bullet.emmiterId) {
                        const battleInfo = queryItemEntity.component(Comp.Battle.BattleInfo)
                        const targetTransform = queryItemEntity.component(Comp.Transform)
                        const distance = MathUtils.getDistanceToLine(targetTransform.pos, ray.startPos, ray.targetPos)
                        if (distance > (ray.width)) {
                            continue
                        }

                        this.world.removeEntity(queryItemEntity.id)
                    }



                }

            })
        }

    }
}